﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MvcWiki.Repository;
using MvcWiki.Model;
using MvcWiki.Exceptions;
using MvcWiki.User;

namespace MvcWiki.Service
{
    public class WikiPageService : IWikiPageService
    {
        IWikiRepositoryFactory RepositoryFactory;
        IUnitOfWork UnitOfWork;
        IWikiUserProvider WikiUserProvider;

        public WikiPageService(IWikiRepositoryFactory repositoryFactory, IUnitOfWork unitOfWork, IWikiUserProvider wikiUserProvider)
        {
            this.RepositoryFactory = repositoryFactory;
            this.UnitOfWork = unitOfWork;
            this.WikiUserProvider = wikiUserProvider;
        }

        public IList<WikiPage> GetAllWikiPages(string wikiNamespaceName)
        {
            var wikiNamespace = RepositoryFactory.GetWikiNamespaceRepository().GetWikiNamespace(wikiNamespaceName);

            if (!WikiUserProvider.CanIndexPages(wikiNamespace))
            {
                throw new MvcWiki.Exceptions.AuthorizationException();
            }

            return RepositoryFactory.GetWikiPageRepository().GetAllWikiPages(wikiNamespaceName);
        }

        public WikiPage GetWikiPage(string wikiNamespaceName, string wikiPageName)
        {
            var wikiNamespace = RepositoryFactory.GetWikiNamespaceRepository().GetWikiNamespace(wikiNamespaceName);

            if (!WikiUserProvider.CanViewNamespace(wikiNamespace))
            {
                throw new MvcWiki.Exceptions.AuthorizationException();
            }

            var wikiPage = RepositoryFactory.GetWikiPageRepository().GetWikiPage(wikiNamespaceName, wikiPageName);

            if (!WikiUserProvider.CanViewPage(wikiPage))
            {
                throw new MvcWiki.Exceptions.AuthorizationException();
            }

            return wikiPage;
        }

        public WikiPage CreateWikiPage(WikiNamespace wikiNamespace, string wikiPageName)
        {
            if (!WikiUserProvider.CanEditNamespace(wikiNamespace))
            {
                throw new MvcWiki.Exceptions.AuthorizationException();
            }

            if (!WikiUserProvider.CanCreatePage())
            {
                throw new MvcWiki.Exceptions.AuthorizationException();
            }

            var wikiPage = new WikiPage
            {
                Name = wikiPageName,
                Namespace = wikiNamespace
            };

            RepositoryFactory.GetWikiPageRepository().SaveWikiPage(wikiPage);

            UnitOfWork.Commit();

            return wikiPage;
        }

        public void SaveWikiPage(WikiPage wikiPage)
        {
            if (!WikiUserProvider.CanEditNamespace(wikiPage.Namespace))
            {
                throw new MvcWiki.Exceptions.AuthorizationException();
            }

            if (!WikiUserProvider.CanEditPage(wikiPage))
            {
                throw new MvcWiki.Exceptions.AuthorizationException();
            }

            RepositoryFactory.GetWikiPageRepository().SaveWikiPage(wikiPage);

            UnitOfWork.Commit();
        }

        public void DeleteWikiPage(string wikiNamespaceName, string wikiPageName)
        {
            var wikiPageRepository = RepositoryFactory.GetWikiPageRepository();

            var wikiPage = wikiPageRepository.GetWikiPage(wikiNamespaceName, wikiPageName);

            if (!WikiUserProvider.CanEditNamespace(wikiPage.Namespace))
            {
                throw new MvcWiki.Exceptions.AuthorizationException();
            }

            if (!WikiUserProvider.CanDeletePage(wikiPage))
            {
                throw new MvcWiki.Exceptions.AuthorizationException();
            }

            wikiPageRepository.DeleteWikiPage(wikiPage);

            UnitOfWork.Commit();
        }
    }
}
